package com.kabu.guardedsuspension;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate;

/**
 * @author jiawuwei
 * @Copyright: Copyright (c) 兆日科技股份有限公司  2020
 * @date 2020/7/22,10:55
 */
public class GuardedObject<T> {
    //受保护的对象
    T obj;
    final Lock lock = new ReentrantLock();
    final Condition done = lock.newCondition();
    final int TIMEOUT = 2;
    //所有受保护的对象
    final static Map<Object,GuardedObject> gos = new ConcurrentHashMap<>();

    /**
     * 创建guardedObject
     * @param key
     * @param <K>
     * @return
     */
    static <K> GuardedObject create(K key){
        GuardedObject<Object> go = new GuardedObject<>();
        gos.put(key,go);
        return go;
    }

    static <K,T> void fireEvent(K key,T obj){
        GuardedObject go = gos.remove(key);
        if(go!=null){
            go.onChanged(obj);
        }
    }

    /**
     * 客户获取受保护的对象
     */
    T get(Predicate<T> p){
        lock.lock();
        try {
            while (!p.test(obj)){
                done.await(TIMEOUT, TimeUnit.SECONDS);
            }
        }catch (InterruptedException  e){
            e.printStackTrace();
            throw new RuntimeException(e);
        }finally {
            lock.unlock();
        }
        return obj;
    }
    /**
     * 当服务员打扫完房间后
     * @param obj
     */
    private void onChanged(T obj) {
        lock.lock();
        try {
            this.obj = obj;
            done.signalAll();
        }finally {
            lock.unlock();
        }
    }
}
